package com.mmall.admin.shiro;

import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author gg
 * @version ShiroConfig.java, v 0.1 2018-05-31 16:02 caofy
 */
@Configuration
@Slf4j
public class ShiroConfig {

    @Bean
    public ShiroFilterFactoryBean createShiroFilter(@Qualifier("securityManager") SecurityManager securityManager) {
        log.info("createShiroFilter start");
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        shiroFilterFactoryBean.setLoginUrl("/admin/login");
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        // 配置不会被拦截的链接 顺序判断 anon:不做任何校验 authc:必须登录 perms:必须有权限
        filterChainDefinitionMap.put("/admin/logout", "logout");
        // feign 接口需要放开权限
        filterChainDefinitionMap.put("/mmall-cache/**", "anon");
        filterChainDefinitionMap.put("/admin/login", "anon");
        filterChainDefinitionMap.put("/druid/**", "anon");
        filterChainDefinitionMap.put("/admin/getShopMenu", "authc");
        filterChainDefinitionMap.put("/resource/menu", "authc");
        filterChainDefinitionMap.put("/common/**", "authc");

        log.info("filterChainDefinitionMap=" + filterChainDefinitionMap);
        filterChainDefinitionMap.put("/**", "perms");
        Map<String, Filter> filters = new HashMap<>(16);
        Filter loginFilter = new LoginFormFilter();
        Filter logoutFormFilter = new LogoutFormFilter();
        Filter permsFilter = new PermsFilter();
        filters.put("logout", logoutFormFilter);
        filters.put("authc", loginFilter);
        filters.put("perms", permsFilter);
        //此处使用自定义的拦截器,autho默认使用FormAuthenticationFilter拦截器
        shiroFilterFactoryBean.setFilters(filters);
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        log.info("createShiroFilter end");
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        return shiroFilterFactoryBean;
    }


    /**
     * 身份认证realm; (自定义账号密码校验；以及加载权限等)
     */
    @Bean(name = "myShiroRealm")
    public AdminShiroRealm myShiroRealm() {
        return new AdminShiroRealm();
    }


    @Bean("securityManager")
    public SecurityManager securityManager(SessionDaoConfig sessionDaoConfig) {
        DefaultWebSecurityManager def = new DefaultWebSecurityManager();
        def.setRealm(myShiroRealm());
        // 自定义session管理 使用redis
        SessionConfig sessionConfig = new SessionConfig();
        sessionConfig.setSessionDAO(sessionDaoConfig);
        MmallSessionFactory mmallSessionFactory = new MmallSessionFactory();
        sessionConfig.setSessionFactory(mmallSessionFactory);
        def.setSessionManager(sessionConfig);
        // 自定义缓存实现 使用redis
        return def;
    }


    /**
     * 开启shiro aop注解支持.
     * 使用代理方式;所以需要开启代码支持;
     *
     * @param securityManager SecurityManager
     * @return AuthorizationAttributeSourceAdvisor
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor =
                new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

}
